home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / plnk081.zip / pilot-link.0.8.1 / libcc / iambicExpense.cc < prev    next >
C/C++ Source or Header  |  1997-05-23  |  8KB  |  299 lines

  1. #include <ctype.h>        // isspace
  2. #include <stdio.h>        // sprintf
  3. #include <stdlib.h>        // strtoul
  4. #include <string.h>        // strcpy
  5. #include <math.h>        // floor
  6. #include "pi-source.h"
  7. #include "pi-iambicExpense.h"
  8.  
  9. /*
  10.  * I left these field names the same as Iambic used, even though the three
  11.  * I put a comment next to seem strangely named.
  12.  */
  13.  
  14. #define hasNote 0x01
  15. #define hasActivity 0x02        /* The type field */
  16. #define hasProject 0x04         /* The payee field */
  17. #define hasClient 0x08          /* The paid by field */
  18. #define hasExchangeRate 0x10
  19. #define hasOdometer 0x20
  20. #define hasAmount 0x40
  21. #define whenInfoChanged 0x80
  22. #define hasOptions 0x100
  23.  
  24.  
  25. iambicExpenseAppInfo_t::iambicExpenseAppInfo_t(void *ai) 
  26.      : appInfo_t(ai) 
  27. {
  28.      unsigned char *ptr = ((unsigned char *) ai) + BASE_APP_INFO_SIZE;
  29.  
  30.      (void) memcpy(_conversionNames, ptr, 256);
  31. }
  32.  
  33. iambicExpenseList_t::~iambicExpenseList_t() 
  34. {
  35.      iambicExpense_t *next;
  36.      
  37.      for (iambicExpense_t *head = _head; head != NULL; head = next) {
  38.           next = head->_next;
  39.           delete head;
  40.      }
  41. }
  42.  
  43. // We can't just point to the data, as it might be deleted.  Make a copy
  44. void iambicExpenseList_t::merge(iambicExpense_t &iambicExpense) 
  45. {
  46.      iambicExpense._next = _head;
  47.      _head = new iambicExpense_t(iambicExpense);
  48. }
  49.  
  50. // We can't just point to the data in the list, as it might get deleted on
  51. // us. We need to make a real copy
  52. void iambicExpenseList_t::merge(iambicExpenseList_t &list) 
  53. {
  54.      iambicExpense_t *newguy;
  55.  
  56.      for (iambicExpense_t *ptr = list._head; ptr != NULL; ptr = ptr->_next) {
  57.           newguy = new iambicExpense_t(ptr);
  58.           newguy->_next = _head;
  59.           _head = newguy;
  60.      }
  61. }
  62.  
  63. /*
  64.  * Palm used a really annoying method of encryption armor for their floating
  65.  * point amounts.  It took forever, but with huge amounts of help from 
  66.  * Kenneth Albanowski we were able to decode it.
  67.  *
  68.  * Note the double pointer to an unsigned char here.  I did that so that this
  69.  * function can increment the pointer that is passed in so that the caller
  70.  * doesn't have to remember to do so every time.
  71.  */
  72. static double getDouble(unsigned char **buf, int isExchangeRate)
  73. {
  74.      unsigned char *ptr = *buf;
  75.      
  76.      char hexbuf[9];
  77.      (void) sprintf(hexbuf, "%lx", get_long(ptr));
  78.      unsigned long div = strtoul(hexbuf, (char **)NULL, 16);
  79.      
  80.      int x = get_byte(ptr + 5) - 0xda;
  81.      
  82.      double min = 0.78125 * (1 << x);
  83.      double max = 0.78125 * (1 << (x + 1));
  84.  
  85.      double amount = (div - 0x80000000) / (0x80000000 * 1.0);
  86.      amount *= max - min;
  87.      amount += min;
  88.  
  89.      /* If it's an exchange rate save precision to 3 decimal places, not 2 */
  90.      if (isExchangeRate)
  91.       amount = floor(amount * 10.0) / 1000.0;
  92.      else
  93.       amount = floor(amount) / 100.0;
  94.      
  95.      /*
  96.       * Move over the value, which is 6 bytes.  There seems to be two
  97.       * bytes following every value.  They are always 0x01 0x00 but I
  98.       * have no clue what they are for.
  99.       */
  100.      
  101.      *buf += 8;
  102.      
  103.      return amount;
  104. }
  105.  
  106. /* Note the double pointer, just like in getDouble above */
  107. static char *getString(unsigned char **buf) 
  108. {
  109.      /* This had better not ever happen! */
  110.      if (**buf == '\0')
  111.       return NULL;
  112.  
  113.      unsigned char *ptr = *buf;
  114.      
  115.      while (isspace(*ptr))
  116.       ptr++;
  117.  
  118.      unsigned char *end;
  119.      for (end = ptr; *end != '\0'; end++)
  120.       ;
  121.  
  122.      /*
  123.       * We need to chop off any trailing whitespace, but at the same time
  124.       * we need to remember where the end of the field was so that we can
  125.       * move over it accordingly.
  126.       */
  127.      unsigned char *realEnd = end;
  128.      
  129.      end--;
  130.      while (isspace(*end))
  131.       end--;
  132.      *(++end) = '\0';
  133.  
  134.      /*
  135.       * end - ptr will move us to the null byte.  Add one more to go past
  136.       * it so we can grab the next string, if it exists.
  137.       */
  138.      *buf += realEnd - ptr + 1;
  139.  
  140.      char *ret = new char [strlen((const char *) ptr) + 1];
  141.      return strcpy(ret, (const char *) ptr);
  142. }
  143.  
  144. /*
  145.  * Format of an expense record:
  146.  * ba 4b 80 00 00 00 ff e1 01 00 00 0b 00 10 c7 4b
  147.  *
  148.  * 2     Date
  149.  * 6     Amount of money
  150.  * 2     Unknown
  151.  * 1     allBits field of an ExpenseDBRecordOptions - Seems unrelavent
  152.  * 1     Flags for reimbursable and receipt available
  153.  * 1     allBits field of an ExpenseDBRecordFlags - Seems unrelavent
  154.  * 1     Flags for record info (hasNote, hasActivity, etc...)
  155.  *
  156.  * This is then followed by the data.  If fields appear, they are separated
  157.  * by two bytes (0x01 0x00), and seem to appear in this order:
  158.  *
  159.  *   exchange rate
  160.  *   odometer begin 0x01 0x00 odometer end
  161.  *   paid by
  162.  *   payee
  163.  *   type
  164.  *   note
  165.  *
  166.  * If odometer is set in the flags, then the amount of money is the number of
  167.  * miles traveled.
  168.  */
  169.  
  170. void iambicExpense_t::unpack(void *buf, int firstTimeThrough) 
  171. {
  172.      if (firstTimeThrough == 0) {
  173.       if (_paidby)
  174.            delete _paidby;
  175.       if (_payee)
  176.            delete _payee;
  177.       if (_type)
  178.            delete _type;
  179.       if (_note)
  180.            delete _note;
  181.      }
  182.      
  183.      unsigned char *ptr = (unsigned char *) buf;
  184.      
  185.      unsigned short d = (unsigned short) get_short(ptr);
  186.  
  187.      /*
  188.       * This is what the pilot stores for the date:
  189.       *
  190.       * typedef struct {
  191.       *   Word year  :7;
  192.       *   Word month :4; 
  193.       *   Word day   :5;
  194.       * } DateType;
  195.       *
  196.       *
  197.       * We want to pop the last 9 bits (the month and day) off
  198.       * of the struct, and move the year bits down to the lower
  199.       * bits.  That's the shift.
  200.       *
  201.       * The 4 is because of OS differences.  The pilot saves the
  202.       * date in macintosh time format, since that's what the
  203.       * dragonball chip uses.  Macs reference the year as of 1904.
  204.       * UNIX, on the other hand, references the year as of 1900.  So
  205.       * we have to add 4 to the number of years to make UNIX happy.
  206.       */
  207.      
  208.      _date.tm_year = (d >> 9) + 4;
  209.       
  210.      /*
  211.       * Drop off the 5 bites of the day.  Then & with the last 4
  212.       * bits so we only get the month part.  Then subtract 1 since
  213.       * a tm_mon is referenced from 0 on UNIX
  214.       */
  215.      _date.tm_mon = ((d >> 5) & 0xF) - 1;
  216.      
  217.      /* Just take the last 5 bits for a day */
  218.      _date.tm_mday = d & 0x1F;
  219.      
  220.      /* We don't know if daylight savings time is in effect */
  221.      _date.tm_isdst = -1;
  222.      
  223.      mktime(&_date);
  224.      
  225.      ptr += 2;
  226.      _amount = getDouble(&ptr, 0);
  227.      
  228.      // Used to be:  options = *++ptr; ptr += 2;
  229.      ptr += 3;
  230.      
  231.      _flags = *ptr++;
  232.      
  233.      if (_flags & hasExchangeRate)
  234.       _exchangeRate = getDouble(&ptr, 1);
  235.      else
  236.       _exchangeRate = 1.0;
  237.      
  238.      if (_flags & hasOdometer) {
  239.       _milesStart = getDouble(&ptr, 0);
  240.       _milesEnd = getDouble(&ptr, 0);
  241.      }
  242.      
  243.      if (_flags & hasClient)
  244.       _paidby = getString(&ptr);
  245.      else
  246.       _paidby = NULL;
  247.           
  248.      if (_flags & hasProject)
  249.       _payee = getString(&ptr);
  250.      else
  251.       _payee = NULL;
  252.      
  253.      if (_flags & hasActivity)
  254.       _type = getString(&ptr);
  255.      else
  256.       _type = NULL;
  257.      
  258.      if (_flags & hasNote)
  259.       _note = getString(&ptr);
  260.      else
  261.       _note = NULL;
  262. }
  263.  
  264. iambicExpense_t::iambicExpense_t(const iambicExpense_t &oldCopy)
  265.      : baseApp_t()
  266. {
  267.      (void) memcpy(this, &oldCopy, sizeof(iambicExpense_t));
  268.  
  269.      if (_paidby) {
  270.       _paidby = new char[strlen(oldCopy._paidby) + 1];
  271.       (void) strcpy(_paidby, oldCopy._paidby);
  272.      }
  273.      if (_payee) {
  274.       _payee = new char[strlen(oldCopy._payee) + 1];
  275.       (void) strcpy(_payee, oldCopy._payee);
  276.      }
  277.      if (_type) {
  278.       _type = new char[strlen(oldCopy._type) + 1];
  279.       (void) strcpy(_type, oldCopy._type);
  280.      }
  281.      if (_note) {
  282.       _note = new char[strlen(oldCopy._note) + 1];
  283.       (void) strcpy(_note, oldCopy._note);
  284.      }
  285. }
  286.  
  287. iambicExpense_t::~iambicExpense_t() 
  288. {
  289.      if (_paidby)
  290.       delete _paidby;
  291.      if (_payee)
  292.       delete _payee;
  293.      if (_type)
  294.       delete _type;
  295.      if (_note)
  296.       delete _note;
  297. }
  298.  
  299.